import datetime
import re
import time
from typing import Union

import pendulum
import pytz


class DT:

    @staticmethod
    def sleep(s):
        time.sleep(s)

    @staticmethod
    def show_sleep(t):
        print(f'无待下载视频，程序休眠。。。')
        for i in range(t):
            print(f'休眠剩余{t - i}秒')
            time.sleep(1)

    @staticmethod
    def date2ts(date: datetime.date) -> int:
        '''
        :param date: <class 'datetime.date'> 类型, 形如 2018-08-12
        或者 <class 'str'> 类型 形如 '2018-08-12'
        :return: <class 'int'> 类型 形如 1534003200
        '''
        datestr_format = "%Y-%m-%d"
        timeArray = None
        if isinstance(date, datetime.date):
            timeArray = time.strptime(date.strftime(datestr_format), datestr_format)
        elif isinstance(date, str):
            timeArray = time.strptime(date, datestr_format)
        timeStamp = int(time.mktime(timeArray))
        return timeStamp

    @staticmethod
    def ts2ds(timeStamp: int) -> str:
        '''
        :param timeStamp:  int 时间戳， 形如：1534052846
        :return: datestr str 形如："2018-08-12"
        '''
        timeArray = time.localtime(timeStamp)
        datestr = time.strftime("%Y-%m-%d", timeArray)
        return datestr

    @staticmethod
    def ts2dt(timeStamp: int) -> datetime.datetime:
        '''
        时间戳 转 年-月-日 时:分:秒 <class 'datetime.date'> 类型
        :param timeStamp,  int 时间戳， 形如：1534052846
        :return: dt, <class 'datetime.datetime'> 类型 形如：2018-08-12 13:47:26
        '''
        timeArray = time.localtime(timeStamp)

        dt = datetime.datetime(
            year=timeArray.tm_year,
            month=timeArray.tm_mon,
            day=timeArray.tm_mday,
            hour=timeArray.tm_hour,
            minute=timeArray.tm_min,
            second=timeArray.tm_sec,
            microsecond=0
        )
        return dt

    @staticmethod
    def ts2dts(timeStamp: int, timezone='Asia/Shanghai') -> str:
        '''
        时间戳 -> 年-月-日 时:分:秒
        :param timeStamp,  int 时间戳， 形如：1534052846
        :return: dts, str 形如："2018-08-12 13:47:26"
        '''
        # 将时间戳转换为datetime对象
        utc_datetime = datetime.datetime.utcfromtimestamp(timeStamp)

        # 将时区字符串转换为时区对象
        target_timezone = pytz.timezone(timezone)

        # 将datetime对象转换为目标时区的时间
        target_datetime = utc_datetime.replace(tzinfo=pytz.utc).astimezone(target_timezone)

        # 将目标时间转换为年月日时分秒字符串
        datetime_str = target_datetime.strftime("%Y-%m-%d %H:%M:%S")

        return datetime_str

    @staticmethod
    def ds2ts(datestr: Union[str, datetime.datetime, datetime.date]) -> int:
        '''
        :param datestr: 日期字符串 形如： "2020-07-06"
        :return: int 时间戳 形如：1593964800
        '''
        if isinstance(datestr, datetime.datetime) or isinstance(datestr, datetime.date):
            datestr = str(datestr)
        datestr_format = "%Y-%m-%d"
        timeArray = time.strptime(datestr, datestr_format)
        timeStamp = int(time.mktime(timeArray))
        return timeStamp

    @staticmethod
    def date_str2date(date_str: str) -> datetime.date:
        '''
        :param datestr: 日期字符串 形如： "2020-07-06"
        :return: date <class 'datetime.date'>  形如 2020-07-06
        '''
        date = datetime.datetime.strptime(date_str, '%Y-%m-%d').date()
        return date

    @staticmethod
    def datetime_str2datetime(datetime_str: str) -> datetime.datetime:
        '''
        :param datestr: 日期字符串 形如： "2018-08-12 13:47:26"
        :return: date <class 'datetime.datetime'>  形如 2018-08-12 13:47:26
        '''
        dt = datetime.datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S')
        return dt

    @staticmethod
    def dt2ts(dts: Union[str, datetime.datetime, datetime.date]) -> int:
        '''
        # 日期时间字符串转时间戳
        :param dts:  datetime 字符串，形如："2020-07-06 14:31:34"
        :return:  int 时间戳 形如：1594017094
        '''
        if isinstance(dts, datetime.datetime) or isinstance(dts, datetime.date):
            dts = str(dts)
        if '-' in dts and ':' in dts:
            dts_format = "%Y-%m-%d %H:%M:%S"
        elif '-' in dts:
            dts_format = "%Y-%m-%d"

        timeArray = time.strptime(dts, dts_format)
        timeStamp = int(time.mktime(timeArray))
        return timeStamp

    @staticmethod
    def get_the_date_from_a_date(date_str: str, days_delta=0) -> str:
        '''比如获取2019-07-23这一天之后days_delta天的日期'''
        year, month, day = [int(i) for i in date_str.split('-')]
        date = datetime.datetime(year, month, day)
        result_date = date + datetime.timedelta(days=days_delta)
        date_str = result_date.strftime('%Y-%m-%d')
        return date_str

    @staticmethod
    def today() -> datetime.date:
        '''返回值类型<class 'datetime.date'>'''
        today = datetime.date.today()
        return today

    @staticmethod
    def tomorrow() -> datetime.date:
        '''返回值类型<class 'datetime.date'>'''
        today = datetime.date.today()
        tomorrow = today + datetime.timedelta(days=1)
        return tomorrow

    @staticmethod
    def yesterday() -> datetime.date:
        '''返回值类型<class 'datetime.date'>'''
        today = datetime.date.today()
        yesterday = today - datetime.timedelta(days=1)
        return yesterday

    @staticmethod
    def datediff(beginDatestr: str, endDatestr: str) -> int:
        '''参数类型:str, 返回值类型: int'''
        format = "%Y-%m-%d"
        bd = datetime.datetime.strptime(beginDatestr, format)
        ed = datetime.datetime.strptime(endDatestr, format)
        days = (bd - ed).days
        return days

    @staticmethod
    def get_date_str_from_today(
            years=0,
            months=0,
            weeks=0,
            days=0,
            hours=0,
            minutes=0,
            seconds=0,
            microseconds=0,
    ) -> str:
        date_str = str(pendulum.today(
            tz="Asia/Shanghai"
        ).add(
            years=years,
            months=months,
            weeks=weeks,
            days=days,
            hours=hours,
            minutes=minutes,
            seconds=seconds,
            microseconds=microseconds,
        )).split('T')[0]
        '''2008-01-01格式'''
        return date_str

    # 时间戳转日期
    @staticmethod
    def timestamp2datetime(timestamp: int, format='ys') -> str:
        """
        将int 类型的timeStamp,eg:1571234123
        转为str类型的时间字符串,eg:2019-10-16 21:55:23
        """
        time_local = time.localtime(timestamp)
        datetime = ''
        if format == 'ys':
            datetime = time.strftime("%Y-%m-%d %H:%M:%S", time_local)
        elif format == 'yd':
            datetime = time.strftime("%Y-%m-%d", time_local)
        elif format == 'hs':
            datetime = time.strftime("%H:%M:%S", time_local)
        return datetime

    @staticmethod
    def get_timestamp_of_today() -> int:
        today = datetime.date.today()
        timeArray = time.strptime(str(today), "%Y-%m-%d")
        timestamp = int(time.mktime(timeArray))
        return timestamp

    @staticmethod
    def now_time_str(date_format="%Y%m%d%H%M%S") -> str:
        now = int(time.time())
        time_local = time.localtime(now)
        str = time.strftime(date_format, time_local)
        return str  # 20190806103523

    @staticmethod
    def trans_date(date_str: str = '20080101') -> str:
        '''
        :param date_str: 字符串类型
        :return: 字符串类型
        '''
        y = date_str[:4]
        m = date_str[4:6]
        d = date_str[-2:]
        date = '-'.join([y, m, d])
        return date

    @staticmethod
    def now_ts(accuracy: str = 's') -> int:
        # 返回值是 int类型
        ts = time.time()
        if accuracy == 's':
            ts = int(ts)
        if accuracy == 'ms':
            ts = int(ts * 1000)
        if accuracy == 'ns':
            ts = int(ts * 1000 * 1000)
        return ts  # 当前时间戳

    @staticmethod
    def now_time() -> str:
        # 返回值是 字符串类型
        now_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")  # 当前时刻
        return now_time

    @staticmethod
    def dt2dt(dt: datetime.datetime) -> datetime.datetime:
        # 返回值是 datetime类型
        now_time = datetime.datetime(
            year=dt.year,
            month=dt.month,
            day=dt.day,
            hour=dt.hour,
            minute=dt.minute,
            second=dt.second
        )
        return now_time

    @staticmethod
    def dts2dt(dts: str):
        # 返回值是 datetime date 或 time类型
        if ' ' in dts:
            d, t = dts.split(' ')
            year, month, day = [int(i) for i in d.split('-')]
            hour, minute, second = [int(i) for i in t.split(':')]
            dt = datetime.datetime(
                year=year,
                month=month,
                day=day,
                hour=hour,
                minute=minute,
                second=second
            )
        else:
            if '-' in dts:
                year, month, day = [int(i) for i in dts.split('-')]
                dt = datetime.date(
                    year=year,
                    month=month,
                    day=day,
                )
            elif ':' in dts:
                hour, minute, second = [int(i) for i in dts.split(':')]
                dt = datetime.time(
                    hour=hour,
                    minute=minute,
                    second=second
                )
            else:
                raise TypeError
        return dt

    @staticmethod
    def datetime_str_verify(datetime_str: str) -> bool:
        """判断是否是一个有效的日期字符串"""
        if '-' in datetime_str and ' ' in datetime_str and ':' in datetime_str:
            try:
                time.strptime(datetime_str, "%Y-%m-%d %H:%M:%S")
                return True
            except Exception as e:
                print(e)
        return False

    @staticmethod
    def date_str_verify(date_str: str) -> bool:
        if '-' in date_str:
            try:
                time.strptime(date_str, "%Y-%m-%d")
                return True
            except Exception as e:
                print(e)
        return False

    @staticmethod
    def time_str_verify(time_str: str) -> bool:
        if ':' in time_str:
            try:
                time.strptime(time_str, "%H:%M:%S")
                return True
            except Exception as e:
                print(e)
        return False

    @staticmethod
    def parse_deltatime(deltatime):
        match = re.match(
            r'(\d+)\s*(hours?|周|week?|weeks?|小时|小時|minutes?|分钟|分鐘|days?|天|个月|months?)\s*(ago|前|之前)',
            deltatime)
        if match:
            num_str = match.group(1)  # 提取数字
            unit_str = match.group(2)  # 提取时间单位
            if unit_str == '分鐘' or unit_str == 'minutes':
                unit_str = '分钟'
            if unit_str == '小時' or unit_str == 'hours':
                unit_str = '小时'
            if unit_str == '天' or unit_str == 'days':
                unit_str = '天'
            if unit_str == '个月' or unit_str == 'months':
                unit_str = '月'
            if unit_str == '周' or unit_str == 'week' or unit_str == 'weeks':
                unit_str = '周'
            num = int(num_str)  # 将数字转换为整型
            return num, unit_str
        else:
            # print(f"deltatime：{deltatime} 未匹配到合法的文本")
            return None, None


if __name__ == '__main__':
    timeStamp = 1534052846
    datestr = DT.ts2ds(timeStamp)
    dts = DT.ts2dts(timeStamp)
    ds = DT.now_time()
    ts = DT.now_ts(accuracy='ns')
    print(f'ds:{ds}')
    print(f'ts:{ts}')
